# import os
# import re
# import uuid
# import datetime
# import shutil
# import aiohttp
# import neo4j
# import yaml
# from fastapi import FastAPI, HTTPException
#
# from py2neo import Graph, Node, Relationship
# from pydantic import BaseModel
# from typing import Dict, List, Tuple, Optional
# import logging
#
# from app.config import settings
#
#
#
# # 配置日志
# logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
# logger = logging.getLogger(__name__)
#
# # 初始化FastAPI应用
# app = FastAPI(title="ER图生成接口服务", description="解析SQL并导入Neo4j（含完整字段属性）")
#
#
# # 请求/响应模型
# class YAMLERGenerateRequest(BaseModel):
#     yaml_url: str
#     er_database: str
#
#
# class YAMLERGenerateResponse(BaseModel):
#     status: str = "success"
#     message: Optional[str] = None
#     data: Optional[Dict] = None
#
#
# class YamlToNeo4jService:
#     def __init__(self):
#         os.makedirs(settings.temp_dir_root, exist_ok=True)
#         self.graph  = None
#
#     def _init_neo4j_graph(self):
#         if not self.graph :
#             try:
#                 # self.driver = GraphDatabase.driver(
#                 #     settings.neo4j_uri,
#                 #     auth=(settings.neo4j_user, settings.neo4j_password)
#                 # )
#                 # self.driver.verify_connectivity()
#                 graph = Graph(settings.neo4j_uri, auth=(settings.neo4j_user, settings.neo4j_password))
#                 self.graph  = graph
#                 logger.info("Neo4j驱动初始化成功")
#             except Exception as e:
#                 logger.error(f"Neo4j驱动初始化失败: {str(e)}")
#                 raise HTTPException(status_code=500, detail=f"无法连接到Neo4j: {str(e)}")
#
#     async def download_sql_file(self, url: str) -> str:
#         # 保持不变（文件下载逻辑）
#         if not url.startswith(settings.dify_prefix) and settings.dify_prefix:
#             full_url = settings.dify_prefix.rstrip("/") + "/" + url.lstrip("/")
#         else:
#             full_url = url
#
#         timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
#         unique_id = uuid.uuid4().hex[:8]
#         temp_dir = os.path.join(settings.temp_dir_root, f"tmp_{timestamp}_{unique_id}")
#         os.makedirs(temp_dir, exist_ok=True)
#
#         filename = url.split("/")[-1]
#         if not filename.endswith(".yaml"):
#             filename = f"er_import_{unique_id}.yaml"
#         file_path = os.path.join(temp_dir, filename)
#
#         try:
#             async with aiohttp.ClientSession() as session:
#                 async with session.get(full_url) as resp:
#                     if resp.status != 200:
#                         logger.error(f"YAML文件下载失败，URL: {full_url}，状态码: {resp.status}")
#                         raise HTTPException(status_code=400, detail=f"YAML文件下载失败，状态码: {resp.status}")
#                     with open(file_path, "wb") as f:
#                         while True:
#                             chunk = await resp.content.read(1024 * 1024)
#                             if not chunk:
#                                 break
#                             f.write(chunk)
#             logger.info(f"YAML文件下载成功，路径: {file_path}")
#             return file_path
#         except Exception as e:
#             logger.error(f"下载过程异常: {str(e)}")
#             raise HTTPException(status_code=500, detail=f"文件下载失败: {str(e)}")
#
#     def parse_type(self,type_str):
#         """解析字段类型字符串（如 VARCHAR(50), DECIMAL(17,2)）"""
#         base_type = type_str
#         length = None
#         precision = None
#
#         if '(' in type_str and ')' in type_str:
#             base_type = type_str.split('(')[0].strip().upper()
#             params = type_str.split('(')[1].split(')')[0]
#
#             if ',' in params:
#                 parts = params.split(',')
#                 length = int(parts[0]) if parts[0].isdigit() else None
#                 precision = int(parts[1]) if len(parts) > 1 and parts[1].isdigit() else None
#             else:
#                 length = int(params) if params.isdigit() else None
#
#         return {
#             "base_type": base_type,
#             "length": length,
#             "precision": precision,
#             "full_type": type_str
#         }
#
#     def import_to_neo4j(self,tables, relationships):
#         self._init_neo4j_graph()
#         graph = self.graph
#         graph.delete_all()  # 清空图谱
#
#         table_nodes = {}
#         column_nodes = {}  # 保存每个字段节点：(table, column) -> Node
#
#         # 创建 Table 和 Column 节点
#
#         for table in tables:
#             table_node = Node(
#                 "Tables From YML",
#                 name=table['table'],
#                 domain=table.get('domain'),
#                 description=table.get('description'),
#                 comment=table.get('comment'),
#                 database=table.get('database')
#             )
#             graph.create(table_node)
#             table_nodes[table['table']] = table_node
#
#             for col in table['columns']:
#                 type_info = self.parse_type(col['type'])
#
#                 col_node = Node(
#                     "Column",
#                     name=col['name'],
#                     base_type=type_info['base_type'],
#                     full_type=type_info['full_type'],
#                     length=type_info['length'],
#                     precision=type_info['precision'],
#                     nullable=col['nullable'],
#                     comment=col.get('comment', ''),
#                     primary_key=col.get('primary_key', False),
#                     foreign_key=col.get('foreign_key', False)
#                 )
#
#                 # 加入 tags 信息为属性
#                 if 'tags' in col:
#                     for key, value in col['tags'].items():
#                         col_node[key] = value
#
#                 graph.create(col_node)
#                 graph.create(Relationship(table_node, "HAS_COLUMN", col_node))
#                 column_nodes[(table['table'], col['name'])] = col_node
#
#         # 创建 FOREIGN_KEY_TO 关系（字段 → 字段）
#         for rel in relationships:
#             source = column_nodes.get((rel['source_table'], rel['source_column']))
#             target = column_nodes.get((rel['target_table'], rel['target_column']))
#             # from_table = rel['source_table']
#             # to_table = rel['target_table']
#             if source and target:
#                 graph.create(Relationship(source, "FOREIGN_KEY_TO", target))
#                 # 加上表之间的引用
#                 # 创建表级引用关系（避免重复创建）
#                 source_table = table_nodes[rel['source_table']]
#                 target_table = table_nodes[rel['target_table']]
#
#                 # 检查是否已存在表级关系
#                 if not graph.relationships.match(
#                         (source_table, target_table), "REFERS_TO"
#                 ).exists():
#                     graph.create(Relationship(source_table, "REFERS_TO", target_table))
#             else:
#                 print(
#                     f"⚠️ 外键引用失败：{rel['source_table']}.{rel['source_column']} → {rel['target_table']}.{rel['target_column']}")
#
#     def extract_foreign_keys(self,tables):
#         """提取字段中显式声明的外键关系"""
#         relationships = []
#
#         for table in tables:
#             for col in table['columns']:
#                 # 检查外键标记和引用信息
#                 if col.get('foreign_key') is True and 'references' in col:
#                     refs = col['references']
#                     # 统一处理为列表
#                     if isinstance(refs, dict):
#                         refs = [refs]
#
#                     for ref in refs:
#                         if isinstance(ref, dict) and 'table' in ref and 'column' in ref:
#                             relationships.append({
#                                 "source_table": table['table'],
#                                 "source_column": col['name'],
#                                 "target_table": ref['table'],
#                                 "target_column": ref['column']
#                             })
#         return relationships
#
#     async def process(self, sql_url: str, database: str) -> Dict:
#         """完整处理流程"""
#         yaml_path = await self.download_sql_file(sql_url)
#
#         with open(yaml_path, 'r', encoding='utf-8') as file:
#             tables = yaml.safe_load(file)
#
#         relationships = self.extract_foreign_keys(tables)
#         self.import_to_neo4j(tables, relationships)
#         print(f"✅ 导入完成：共 {len(tables)} 个表，{len(relationships)} 个外键字段关系")
#
#         # 清理临时文件
#         try:
#             shutil.rmtree(os.path.dirname(yaml_path))
#             logger.info(f"临时文件已清理: {os.path.dirname(yaml_path)}")
#         except Exception as e:
#             logger.warning(f"临时文件清理失败: {str(e)}")
#
#
#
#         return {
#             "tables": {"count": len(tables), "list": tables},
#             "relations": {"count": len(relationships), "list": relationships},
#             "neo4j_import": "success"
#         }